#!/bin/bash

# 数据网关启动脚本
# 作者: Data Gateway Team
# 版本: 1.0.0

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"
}

log_debug() {
    echo -e "${BLUE}[DEBUG]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"
}

# 检查环境变量
check_environment() {
    log_info "检查环境变量..."
    
    # 检查必要的环境变量
    if [ -z "$KAFKA_BOOTSTRAP_SERVERS" ]; then
        log_warn "KAFKA_BOOTSTRAP_SERVERS 未设置，使用默认值: localhost:9092"
        export KAFKA_BOOTSTRAP_SERVERS="localhost:9092"
    fi
    
    if [ -z "$HIVE_JDBC_URL" ]; then
        log_warn "HIVE_JDBC_URL 未设置，使用默认值: jdbc:hive2://hive-server:10000/default"
        export HIVE_JDBC_URL="jdbc:hive2://hive-server:10000/default"
    fi
    
    if [ -z "$HIVE_USERNAME" ]; then
        log_warn "HIVE_USERNAME 未设置，使用默认值: hive"
        export HIVE_USERNAME="hive"
    fi
    
    if [ -z "$HIVE_PASSWORD" ]; then
        log_warn "HIVE_PASSWORD 未设置，使用默认值: hive"
        export HIVE_PASSWORD="hive"
    fi
    
    log_info "环境变量检查完成"
}

# 等待依赖服务
wait_for_dependencies() {
    log_info "等待依赖服务启动..."
    
    # 解析Kafka服务器地址
    IFS=',' read -ra KAFKA_SERVERS <<< "$KAFKA_BOOTSTRAP_SERVERS"
    for server in "${KAFKA_SERVERS[@]}"; do
        IFS=':' read -ra ADDR <<< "$server"
        host=${ADDR[0]}
        port=${ADDR[1]:-9092}
        
        log_info "等待Kafka服务: $host:$port"
        while ! nc -z "$host" "$port"; do
            log_info "等待Kafka服务启动: $host:$port"
            sleep 5
        done
        log_info "Kafka服务已就绪: $host:$port"
    done
    
    # 解析Hive服务器地址
    if [[ $HIVE_JDBC_URL == jdbc:hive2://* ]]; then
        hive_url=${HIVE_JDBC_URL#jdbc:hive2://}
        IFS='/' read -ra PARTS <<< "$hive_url"
        hive_host_port=${PARTS[0]}
        IFS=':' read -ra ADDR <<< "$hive_host_port"
        hive_host=${ADDR[0]}
        hive_port=${ADDR[1]:-10000}
        
        log_info "等待Hive服务: $hive_host:$hive_port"
        while ! nc -z "$hive_host" "$hive_port"; do
            log_info "等待Hive服务启动: $hive_host:$hive_port"
            sleep 5
        done
        log_info "Hive服务已就绪: $hive_host:$hive_port"
    fi
    
    log_info "所有依赖服务已就绪"
}

# 检查JVM参数
check_jvm_options() {
    log_info "检查JVM参数..."
    
    # 设置默认JVM参数
    if [ -z "$JAVA_OPTS" ]; then
        export JAVA_OPTS="-Xms512m -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+UseStringDeduplication"
        log_info "使用默认JVM参数: $JAVA_OPTS"
    else
        log_info "使用自定义JVM参数: $JAVA_OPTS"
    fi
    
    # 添加生产环境JVM参数
    export JAVA_OPTS="$JAVA_OPTS -Djava.security.egd=file:/dev/./urandom"
    export JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=${SPRING_PROFILES_ACTIVE:-prod}"
    export JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8"
    export JAVA_OPTS="$JAVA_OPTS -Duser.timezone=${TZ:-Asia/Shanghai}"
    
    log_info "最终JVM参数: $JAVA_OPTS"
}

# 创建必要的目录
create_directories() {
    log_info "创建必要的目录..."
    
    mkdir -p /app/logs
    mkdir -p /app/config
    mkdir -p /app/scripts
    mkdir -p /app/data
    mkdir -p /app/backup
    
    log_info "目录创建完成"
}

# 检查配置文件
check_config_files() {
    log_info "检查配置文件..."
    
    if [ ! -f "/app/config/application.yml" ]; then
        log_warn "配置文件不存在，使用默认配置"
        cp /app/app.jar /tmp/app.jar
        jar xf /tmp/app.jar BOOT-INF/classes/application.yml
        mv BOOT-INF/classes/application.yml /app/config/
        rm -rf BOOT-INF
        rm -f /tmp/app.jar
    fi
    
    if [ ! -f "/app/config/application-prod.yml" ]; then
        log_warn "生产环境配置文件不存在，使用默认配置"
        cp /app/app.jar /tmp/app.jar
        jar xf /tmp/app.jar BOOT-INF/classes/application-prod.yml
        mv BOOT-INF/classes/application-prod.yml /app/config/
        rm -rf BOOT-INF
        rm -f /tmp/app.jar
    fi
    
    log_info "配置文件检查完成"
}

# 健康检查
health_check() {
    log_info "执行健康检查..."
    
    # 等待应用启动
    sleep 30
    
    # 检查应用是否响应
    for i in {1..30}; do
        if curl -f http://localhost:8080/data-gateway/api/health/status > /dev/null 2>&1; then
            log_info "应用健康检查通过"
            return 0
        fi
        log_info "等待应用启动... ($i/30)"
        sleep 10
    done
    
    log_error "应用健康检查失败"
    return 1
}

# 优雅关闭
graceful_shutdown() {
    log_info "接收到关闭信号，开始优雅关闭..."
    
    # 发送SIGTERM信号给Java进程
    if [ ! -z "$JAVA_PID" ]; then
        kill -TERM "$JAVA_PID"
        
        # 等待进程结束
        for i in {1..30}; do
            if ! kill -0 "$JAVA_PID" 2>/dev/null; then
                log_info "应用已优雅关闭"
                return 0
            fi
            log_info "等待应用关闭... ($i/30)"
            sleep 2
        done
        
        # 强制关闭
        log_warn "强制关闭应用"
        kill -KILL "$JAVA_PID" 2>/dev/null || true
    fi
}

# 设置信号处理
setup_signal_handlers() {
    trap 'graceful_shutdown' SIGTERM SIGINT
}

# 主函数
main() {
    log_info "启动数据网关应用..."
    log_info "版本: 1.0.0"
    log_info "环境: ${SPRING_PROFILES_ACTIVE:-prod}"
    
    # 设置信号处理
    setup_signal_handlers
    
    # 检查环境
    check_environment
    
    # 等待依赖服务
    wait_for_dependencies
    
    # 检查JVM参数
    check_jvm_options
    
    # 创建目录
    create_directories
    
    # 检查配置文件
    check_config_files
    
    # 启动应用
    log_info "启动Java应用..."
    log_info "JVM参数: $JAVA_OPTS"
    log_info "配置文件: /app/config/"
    log_info "日志目录: /app/logs/"
    
    # 启动Java应用
    exec java $JAVA_OPTS -jar /app/app.jar \
        --spring.config.location=classpath:/,file:/app/config/ \
        --logging.file.name=/app/logs/data-gateway.log \
        --server.port=8080 \
        "$@" &
    
    # 保存Java进程PID
    JAVA_PID=$!
    
    # 健康检查
    if health_check; then
        log_info "数据网关应用启动成功"
        log_info "PID: $JAVA_PID"
        log_info "健康检查地址: http://localhost:8080/data-gateway/api/health/status"
        log_info "管理端点: http://localhost:8080/actuator"
        
        # 等待进程结束
        wait $JAVA_PID
    else
        log_error "数据网关应用启动失败"
        exit 1
    fi
}

# 执行主函数
main "$@"
